import asyncio
import json
import logging

from tornado import gen

from baseHandler import Application, PayHandler, init_logger, http_result

logger = init_logger("unionpay", "/data/log/unionpay/unionpay.log")


class UnionpayEntrust(PayHandler):
    @gen.coroutine
    def post(self):
        exited = yield self.merchant_exit()
        if not exited:
            logger.info("商户不存在")
            return self.write(json.dumps({"message": "商户不存在", "ret": -1}))
        if not self.check_ip():
            return self.write(json.dumps({"message": "ip错误", "ret": -1}))
        if not self.check_sign():
            logger.info("签名验证失败")
            return self.write(json.dumps({"message": "签名验证失败", "ret": -1}))
        data = self.decrypt()
        if not data:
            return self.write({"message": "解密失败", "ret": -1})
        data = json.loads(data)
        logger.info(data)
        # 检查data 参数
        # TODO
        res = self.check_ordernumber(data)
        if res:
            return self.write({"message": "订单号格式错误", "ret": -1})

        bankunion = data.get('bankunion', '')

        if data['accounttype'] == '0' and not bankunion:
            return self.write({"message": "缺少联行号", "ret": -1})


        # 请求到核心参数'
        merchantid = data.get('merchantid', self.merchantid)
        logger.info('%s|银联协议代付|订单号%s|金额%s', self.merchantid, data["ordernumber"], data["amount"])
        input_json = {
            "DEPTID": "800001",
            "OPERID": "9527",
            "FUNCTYPE": "MPAY",
            "FUNCCODE": "200104",
            "OPERPASS": "f15dbcb3154d37e4a183a350e4e8a15dde16a175",
            "REQINFO": {
                "MERCHANTID": merchantid,
                "MERCHANTORDERNO": str(data["ordernumber"]),
                "OPMONEY": str(data["amount"]),
                "BIZID": "PAY.UNIONPAY.ENTRUST",
                "NOTIFYURL": data["backurl"],
                "RETURNURL": "",
                "CLIENTIP": self.remote_ip,
                "PAYSOURE": "CP01",
                "CARDNO": data["bankaccount"],
                "CUSTNAME": data["accountname"],
                "CERDID": data.get("cerdid", ""),
                "CERDTYPE": data.get("credtype", ""),
                "BANKUNION": bankunion

            }
        }

        logger.info(input_json)
        core_response = yield from self.pay_core("PAY_UNIONPAY_ENTRUST_REQ", input_json)

        logger.info(core_response)
        # 处理核心返回结果
        if core_response['RETREDIRECT'] == "PAY.CORE.EBS":
            logger.warn("%s|银联协议代付|订单号%s|-1|%s", merchantid, data['ordernumber'], core_response["MESSAGE"])
            return self.write({"ret": -1, "message": core_response["MESSAGE"]})
        else:
            # 请求上游
            channel = self.get_channel(core_response['PAYCHANNEL'])
            request_obj = {
                "CFGPARA": core_response["CFGPARA"],
                "OPMONEY": core_response["OPMONEY"],
                "OUTERORDERNO": core_response["OUTERORDERNO"],
                "PAYCHANNEL": core_response["PAYCHANNEL"],
                "ACCOUNTNAME": data["accountname"],
                "BANKACCOUNT": data["bankaccount"],
                "ACCOUNTTYPE": data["accounttype"],
                "BANK": data["bank"],
                # "bankcode": data["bankcode"],
            }
            if core_response['BANKUNION'] != '000000000000':
                request_obj.update({"bankcode": core_response["BANKUNION"] or bankunion})
            logger.info(request_obj)
            response = yield http_result(channel, request_obj)
            # logger.info(response.body.decode('utf-8'))
            # 处理上游应答
            if len(response.body) > 8 and response.code == 200:
                channel_result = json.loads(response.body.decode("utf-8"))
                logger.info('%s|银联协议代付|订单号%s|支付结果%s', merchantid, data['ordernumber'],
                            channel_result.get("ORDERSTATE", ""))
            else:
                logger.info('%s|银联协议代付|订单号%s|支付结果%s', merchantid, data['ordernumber'],
                            response.body.decode("utf-8"))
                channel_result = {}

            input_json = {
                "DEPTID": "800001",
                "OPERID": "9527",
                "FUNCTYPE": "RESP",
                "FUNCCODE": "100202",
                "OPERPASS": "f15dbcb3154d37e4a183a350e4e8a15dde16a175",
                "REQINFO": {
                    "OUTERORDERNO": core_response["OUTERORDERNO"],
                    "PAYORDERNO": core_response["OUTERORDERNO"],
                    "ORDERSTATE": channel_result.get("ORDERSTATE", "9"),
                }
            }
            logger.info(input_json)
            # 应答核心程序
            result = yield from self.pay_core("PAY_UNIONPAY_ENTRUST_RES", input_json)
            logger.info(result)
            if result["MESSAGE"] == "SUCCESS":
                obj = {
                    "ordernumber": result["OUTERORDERNO"],
                    "amount": core_response["OPMONEY"],
                    "respcode": result["ORDERSTATE"]
                }
                result['MERCHANTID'] = self.merchantid
                rsp_obj = self.niti_data(obj, result)
                rsp_obj.update({"ret": int(channel_result["ORDERSTATE"]), "message": "success"})
                return self.write(rsp_obj)
            else:
                return self.write({"ret": -1, "message": result["MESSAGE"]})

        return self.write({"ret": -1, "message": "没有权限"})


class UnionpayQuery(PayHandler):
    @gen.coroutine
    def post(self):
        exited = yield self.merchant_exit()
        if not exited:
            logger.info("商户不存在")
            return self.write(json.dumps({"message": "商户不存在", "ret": -1}))
        if not self.check_ip():
            return self.write(json.dumps({"message": "ip错误", "ret": -1}))
        if not self.check_sign():
            logger.info("签名验证失败")
            return self.write(json.dumps({"message": "签名验证失败", "ret": -1}))
        data = self.decrypt()
        if not data:
            return self.write({"message": "解密失败", "ret": -1})
        data = json.loads(data)
        logger.info(data)
        return self.write({"ret": -1, "message": "没有权限"})


class QueryWallet(PayHandler):
    @gen.coroutine
    def post(self):
        exited = yield self.merchant_exit()
        if not exited:
            logger.info("商户不存在")
            return self.write(json.dumps({"message": "商户不存在", "ret": -1}))
        if not self.check_ip():
            return self.write(json.dumps({"message": "ip错误", "ret": -1}))
        if not self.check_sign():
            logger.info("签名验证失败")
            return self.write(json.dumps({"message": "签名验证失败", "ret": -1}))
        data = self.decrypt()
        if not data:
            return self.write({"message": "解密失败", "ret": -1})
        data = json.loads(data)
        res = self.check_ordernumber(data)
        if res:
            return self.write({"message": "订单号格式错误", "ret": -1})

        logger.info("%s|查询钱包余额|%s", self.merchantid, data["ordernumber"])
        input_json = {
            "DEPTID": "800001",
            "OPERID": "9527",
            "FUNCTYPE": "MPAY",
            "FUNCCODE": "200104",
            "OPERPASS": "f15dbcb3154d37e4a183a350e4e8a15dde16a175",
            "REQINFO": {
                "MERCHANTID": str(self.merchantid),
                "MERCHANTORDERNO": data["ordernumber"],
            }
        }

        core_response = yield from self.pay_core("PAY_CORE_WALLET_QUERY", input_json)
        logger.debug(core_response)
        if core_response['RETREDIRECT'] == "PAY.CORE.EBS" and core_response["MESSAGE"] == "SUCCESS":
            obj = {
                "cashwallet": core_response["CASHWALLET"],
                "datawallet": core_response["DATAWALLET"],
                "holdwallet": core_response["HOLDWALLET"],
                "creditwallet": core_response["CREDITWALLET"]
            }
            logger.info("%s|查询钱包余额|cash:%s|data:%s|hold:%s|credit:%s", self.merchantid, core_response["CASHWALLET"],
                        core_response["DATAWALLET"], core_response["HOLDWALLET"], core_response["CREDITWALLET"])

            return_obj = self.niti_data(obj, core_response)
            return_obj.update({"ret": 0, "message": "success"})
            return self.write(return_obj)
        else:

            return self.write({"ret": -1, "message": core_response["MESSAGE"]})


if __name__ == "__main__":
    handlers = [
        # (r"/", MainHandler),ls
        (r"/pay/unionpay/protocol/entrust", UnionpayEntrust),
        (r"/pay/unionpay/query/entrust", UnionpayQuery),
        (r"/pay/query/wallet", QueryWallet),
    ]

    logger.info("Run unionpay server ... http://127.0.0.1:9997")
    application = Application(handlers)
    application.listen(9997, address="127.0.0.1")

    loop = asyncio.get_event_loop()
    application.init_with_loop(loop)
    loop.run_forever()
